import sys
import re
import pprint
import ConfigParser
import datetime as dt

from collections import defaultdict

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator


def mkdateyear(text):
    return dt.datetime.strptime(text, '%Y-%m-%d')


def plot_frac(fracs):
    x = []
    y = []
    for frac in fracs:
        x.append(frac[0])
        y.append(frac[1])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ind = np.arange(len(x))
    rects1 = ax.barh(ind,y)
    ax.set_yticks(ind + 0.5)
    ax.set_yticklabels(x)
    ax.set_xlabel("Number of faults")
    ax.set_ylabel("Fault type")
    #ax.yaxis.set_major_locator(MaxNLocator(len(x)))
    return


def get_data_from_csv(file_path):
    fil_str = file_path[0]
    print file_path
    f = open(fil_str, 'r')
    para_list = f.readline() \
            .replace(' ','') \
            .replace('\n', '') \
            .replace('\r', '') \
            .replace('(', '') \
            .replace(')','') \
            .replace('-','') \
            .replace('.','') \
            .lower() \
            .split(';')
    # Ensure that there are no empty list in the parameter list required by genfromtxt
    old_para = ""
    for i, para in enumerate(para_list):
        if para == '':
            para_list[i] = "Dummy"
        elif para == old_para:
            para_list[i] = old_para + "2"
        old_para = para_list[i]
    dtyp = [ int,   '|O4',  '|O4',  '|O4',  '|O4',
            '|O4',  '|O4',  '|O4',  '|O4',  float,
            float,  '|O4',  float,  '|O4',  '|O4',
            '|O4',  '|O4',  '|O4',  '|O4',  '|O4',
            '|O4',  '|O4',  float,  float,  '|O4',
            '|O4']

    data = np.genfromtxt(fil_str, delimiter=';',
                        names=para_list,
                        skip_header=1,
                        dtype=dtyp)

    clean_data, data_list = clean_it(data, para_list)
    data_dict = dict(zip(para_list, data_list))
    create_search_dict(data_dict)
    return data, data_dict

def clean_it(data, para_list):
    good_meas = 0
    not_numbered = 0
    num_idx = []
    data_list = []
    for i, num in enumerate(data["nr"]):
        try:
            float(num)
            num_idx.append(i)
            good_meas += 1
        except:
            # it is not a float
            not_numbered += 1
    new_data = data[num_idx][:]

    for i, para in enumerate(para_list):
        data_list.append(data[num_idx][para])

    return new_data, data_list

def create_search_dict(data_dict):
    data_dict["turbine"] = []
    for i, date in enumerate(data_dict["basstartdate"]):
        new_date = mkdateyear(date)
        data_dict["basstartdate"][i] = new_date
        data_dict["turbine"].append(data_dict["functionalloc"][i][0:6].lower())



def find_price(data):
    tot_price = 0
    for price in data["totsumactual"]:
        tot_price += float(price.replace(',',''))
    return tot_price

def rds_pp_sort(data):
    rdspp_dict ={}
    total1 = 0
    rdspp_list = []
    for rdspp in data["changedrdspp"]:
        clean_rdsppp = rdspp.replace('?','').replace(' ', '')
        rdspp_list.append(clean_rdsppp)
        match = re.search(r"^([A-Z]{2,3})([0-9]{2})?([A-Z]{2}[0-9]{3})?", clean_rdsppp)
        if match:
            if match.group(1) in rdspp_dict:
                rdspp_dict[match.group(1)]['total'] = rdspp_dict[match.group(1)]['total'] + 1
            else:
                rdspp_dict[match.group(1)] = {}
                rdspp_dict[match.group(1)]['total'] = 1
            if match.group(2):
                if ''.join(match.group(1,2)) in rdspp_dict[match.group(1)]:
                    rdspp_dict[match.group(1)][''.join(match.group(1,2))]['total'] = \
                            rdspp_dict[match.group(1)][''.join(match.group(1,2))]['total'] + 1
                else:
                    rdspp_dict[match.group(1)][''.join(match.group(1,2))] = {}
                    rdspp_dict[match.group(1)][''.join(match.group(1,2))]['total'] = 1
            if match.group(3):
                if match.group(0) in rdspp_dict[match.group(1)][''.join(match.group(1,2))]:
                    rdspp_dict[match.group(1)][''.join(match.group(1,2))][match.group(0)]['total'] = \
                            rdspp_dict[match.group(1)][''.join(match.group(1,2))][match.group(0)]['total'] + 1
                else:
                    rdspp_dict[match.group(1)][''.join(match.group(1,2))][match.group(0)] = {}
                    rdspp_dict[match.group(1)][''.join(match.group(1,2))][match.group(0)]['total'] = 1
            total1 += 1
        else:
            print "Not found:" + str(rdspp)
    rdspp_list = sorted(rdspp_list)
    new_rdspp_dict = {}
    for i in set(rdspp_list):
        new_rdspp_dict[i] = rdspp_list.count(i)
    #print new_rdspp_dict
    print "Number of different RDS-PP:",
    print len(new_rdspp_dict)
    plot_frac(sorted(new_rdspp_dict.items()))
    plt.show()

    return
    pp = pprint.PrettyPrinter(indent=4, width=20, depth=4)
    #pp.pprint(rdspp_dict)
    frac0 = find_fracs(rdspp_dict.iteritems())
    frac1 = find_fracs(rdspp_dict["MDK"].iteritems())
    #frac2 = find_fracs(rdspp_dict["MDK"]["MDK51"].iteritems())
    plot_frac(frac0)
    plot_frac(frac1)
    plt.show()

def find_fracs(frac_dict):
    fracs = []
    for key, value in frac_dict:
        try:
            fracs.append([key, value["total"]])
        except:
            pass
    return sorted(fracs)

def find_specific_data(data_dict, turbines, time_range):
    """ Give it a list of turbines and a time range and
    then it will list all the sap faults matching this
    """
    turbines = [turb.lower() for turb in turbines]
    specific_data = defaultdict(list)
    new_specific_data = defaultdict(lambda : defaultdict(list))
    count = 0
    for i, turbine in enumerate(data_dict["turbine"]):
        if turbine in turbines or turbines[0] == "":
            time = data_dict["basstartdate"][i]
            if time >= time_range[0] and time <= time_range[1]:
                count += 1
                specific_data["time"].append(time)
                specific_data["turbine"].append(turbine)
                new_specific_data[turbine]["time"].append(time)
                new_specific_data[turbine]["failuretype"].append(data_dict["typefailure"][i])
                new_specific_data[turbine]["describ3"].append(data_dict["descriptionwhnr"][i])
                new_specific_data[turbine]["describ1"].append(data_dict["description"][i])
                specific_data["describ1"].append(data_dict["description"][i])
                specific_data["describ2"].append(data_dict["description2"][i])
                specific_data["describ3"].append(data_dict["descriptionwhnr"][i])
                specific_data["failuretype"].append(data_dict["typefailure"][i])
                specific_data["rdspp"].append(data_dict["changedrdspp"][i])
                specific_data["totalcost"].append(data_dict["totsumactual"][i])
                specific_data["nr"].append(data_dict["nr"][i])
    #print count
    #print_specified_data(new_specific_data, turbines)
    return specific_data

def print_specified_data(specific_data, turbines):
    turbines = sorted(turbines)
    for turbine in turbines:
        print turbine
        inds = np.argsort(specific_data[turbine]["time"])
        for key in specific_data[turbine].keys():
            specific_data[turbine][key] = np.take(specific_data[turbine][key], inds)
        for i, tid in enumerate(specific_data[turbine]["time"]):
            print tid,
            print specific_data[turbine]["failuretype"][i]
            print specific_data[turbine]["describ1"][i],
            print specific_data[turbine]["describ3"][i]
    return
    new_specific_data = defaultdict(lambda : [[]])
    turbines = sorted(turbines)
    for turbine in turbines:
        for i, time in enumerate(specific_data["time"]):
            if turbine == specific_data["turbine"][i]:
                print turbine
                new_specific_data[turbine][0].append(time)
    print new_specific_data

def find_temperature_related_faults(data_dict):
    num_in_grid = 0
    not_in_group = 0
    num_of_temp = 0
    num_of_q8 = 0
    total_num = 0
    for i, num in enumerate(data_dict["nr"]):
        describ_str = data_dict["description"][i].lower() + data_dict["description2"][i].lower() + data_dict["descriptionwhnr"][i].lower()
        match = re.search(r"^(.*thermo.*|.*temp.*|.*termo.*|.*t53.*|.*varm.*)*(.*q8.*)*(.*grid.*)*", describ_str)
        if match.group(1):
            num_of_temp += 1
        if match.group(2):
            num_of_q8 += 1
        if match.group(3):
            num_in_grid += 1
        if not (match.group(1) or match.group(2) or match.group(3)):
            print describ_str
            not_in_group += 1
        total_num += 1
    print "Distribution of faults"
    print num_of_temp
    print num_of_q8
    print num_in_grid
    print not_in_group
    print total_num
    return

def get_data():
    config = ConfigParser.ConfigParser()
    config.read("../config.cfg")
    csv_path = config.get('options', 'csv_path')
    file_path = csv_path + "sap-data-adjustment-rdspp-step-3.csv"
    file_path = [file_path]
    clean_data, data_dict = get_data_from_csv(file_path)
    return data_dict

def main():
    #data = get_data_from_csv("sap-data-orginal")
    data = get_data()
    #find_temperature_related_faults(data)
    rds_pp_sort(data)
    return
    config = ConfigParser.ConfigParser()
    config.read("../config.cfg")
    turbines = tuple(config.get('options', 'turbines').split(','))
    time_range = (dt.datetime(2008,1,1), dt.datetime(2009,1,1))
    csv_path = config.get('options', 'csv_path')
    print time_range
    print turbines
    file_path = csv_path + "sap-data-adjustment-rdspp-step-3.csv"
    file_path = [file_path]

    clean_data, data_dict = get_data_from_csv(file_path)

    #look_at_prio(clean_data)
    find_specific_data(data_dict, turbines, time_range)

    return
    data, data_dict = get_data_from_csv("sap-data-adjustment-rdspp-step-3")
    return
    sod_data = find_sod_numbers(data_dict)
    so_analysis = do_so_analysis(sod_data)
    where_to_look = look_at_so_analysis(so_analysis)
    here_to_look = look_at_describtion(data_dict, where_to_look)
    here_we_go_now(data_dict, here_to_look)
    #find_frequency(data)
    #rds_pp_sort(data)
    #look_at_prio(data)

if __name__=='__main__':
    main()

